package dk.au.cs.peterbn.patterns.impl;

import dk.au.cs.peterbn.patterns.DesignPattern;
import dk.au.cs.peterbn.patterns.MemberRole;
import dk.au.cs.peterbn.patterns.TypeRole;

import java.util.*;

/**
 * Default implementatino of DesignPattern
 */
public class DesignPatternImpl implements DesignPattern, HasModifiableDescription {
    private String name;
    private String group;
    private String description;
    private Map<String, TypeRoleImpl> typeRoles;
    private List<PatternVariationImpl> variations;

    public DesignPatternImpl() {
        this.typeRoles = new HashMap<String, TypeRoleImpl>();
        variations = new ArrayList<PatternVariationImpl>();
        this.description = "";
    }

    @Override
    public Collection<TypeRole> getTypes() {
        return Collections.<TypeRole>unmodifiableCollection(typeRoles.values());
    }

    @Override
    public String getDescription() {
        return description;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getGroup() {
        return group;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    void addTypeRole(TypeRoleImpl typeRole) {
        typeRoles.put(typeRole.getName(), typeRole);
    }

    @Override
    public MemberRole getMember(String name) {
        for (TypeRoleImpl typeRole : typeRoles.values()) {
            MemberRole member = typeRole.getMember(name);
            if (member != null) {
                return member;
            }
        }
        return null;
    }

    @Override
    public TypeRole getTypeRole(String name) {
        return typeRoles.get(name);
    }

    @Override
    public String getVariation() {
        StringBuilder sb = new StringBuilder();
        for (Iterator<PatternVariationImpl> iterator = variations.iterator(); iterator.hasNext(); ) {
            PatternVariationImpl variation = iterator.next();
            sb.append(variation.getName());
            if (iterator.hasNext()) {
                sb.append("/");
            }
        }
        return sb.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        DesignPatternImpl that = (DesignPatternImpl) o;

        if (!group.equals(that.group)) return false;
        //noinspection RedundantIfStatement
        if (!name.equals(that.name)) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = name.hashCode();
        result = 31 * result + group.hashCode();
        return result;
    }

    @Override
    public String getIdentifier() {
        return getGroup() + ":" + getName() + (getVariation() != null && getVariation().length() > 0 ? "/" + getVariation() : "");
    }

    void setName(String name) {
        this.name = name;
    }

    void setGroup(String group) {
        this.group = group;
    }

    Map<String, TypeRoleImpl> getAndClerRoles() {
        Map<String, TypeRoleImpl> tmp = typeRoles;
        typeRoles = new HashMap<String, TypeRoleImpl>();
        return tmp;
    }

    void addVariation(PatternVariationImpl variation) {
        variations.add(variation);
    }
}
